﻿#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/rsa.h>
#include <openssl/pem.h>

#define RSA_PRIVATE_KEY_NAME "kusrpriv.key"
#define RSA_PUBLIC_KEY_NAME "kusrpub.key"

#define FAIL 1
#define SUCCESS 0
#define RESULT int

RESULT  RSA_Encrypt(char *pszSource_file, char *pszObject_file);
RESULT  RSA_Decrypt(char *pszSource_file, char *pszObject_file);
RSA     *RSA_read_privatekey(char *pszSource_file);
RSA     *RSA_read_publickey(char *pszSource_file);


RESULT main(int argc, char *argv[])
{

    char szflag[5];
    char szSource_file[32];
    char szObject_file[32];

    if(argc != 4)
    {
        printf("nUsage: makeDES <flag> <Source file> <Object file> <key>\n");
        printf("flag        -- 标识，为1时进行加密操作，为2时进行解密操作\n");
        printf("Source file -- 源文件\n");
        printf("Object file -- 目标文件\n");
        return FAIL;
    }

    strcpy(szflag,argv[1]);
    strcpy(szSource_file,argv[2]);
    strcpy(szObject_file,argv[3]);

    if(strcmp(szflag, "1") == 0)
    {
        printf("\n您选择的方式是[flag=%s],加密操作\n",szflag);
    }
    else
    {
        printf("\n您选择的方式是[flag=%s],解密操作\n",szflag);
    }
    printf("Source file: %s\n",szSource_file);
    printf("Object file: %s\n",szObject_file);

    if(strcmp(szflag, "1") == 0)
    {
        RSA_Encrypt(szSource_file, szObject_file);
    }
    else
    {
        RSA_Decrypt(szSource_file, szObject_file);
    }

    return SUCCESS;
}

int RSA_Encrypt(char *pszSource_file, char *pszObject_file)
{
    FILE *pfPlain, *pfCipher;
    char *szPlainBlock, *szCipherBlock;
    RSA  *pRsa;
    int  iret = -1, flen, icount = -1, itail = -1;

    if((pfPlain = fopen(pszSource_file, "rb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", pszSource_file);
        return FAIL;
    }
    if((pfCipher = fopen(pszObject_file, "wb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", pszObject_file);
        return FAIL;
    }
    pRsa = RSA_new();
   
    pRsa = RSA_read_publickey(RSA_PUBLIC_KEY_NAME);
    pRsa = RSA_read_privatekey(RSA_PRIVATE_KEY_NAME);
    iret = RSA_check_key(pRsa);
    if(iret != 1)
    {
        printf("key error!\n");
        return FAIL;
    }
   
    flen = RSA_size(pRsa);
    itail = flen - 11;
   
    szPlainBlock = (char*)malloc(flen);
    szCipherBlock = (char*)malloc(flen);
   
    while(!feof(pfPlain)) {
        if(icount = fread(szPlainBlock, sizeof(char), RSA_size(pRsa) - 11, pfPlain)) {
            iret = RSA_public_encrypt(icount, szPlainBlock, szCipherBlock, pRsa, RSA_PKCS1_PADDING);
            if (iret < 0) {
                printf("Encrypt failed!\n");
                return FAIL;
            }
            fwrite(szCipherBlock, sizeof(char), flen, pfCipher);
        }
    }

   
    free(szPlainBlock);
    free(szCipherBlock);
   
    szPlainBlock=NULL;
    szCipherBlock=NULL;
   
    fclose(pfPlain);
    fclose(pfCipher);

    RSA_free(pRsa);
   
    printf("RSA_Encrypt OK!\n");
    return SUCCESS;

}

RESULT RSA_Decrypt(char *pszSource_file, char *pszObject_file)
{
    FILE            *pfPlain, *pfCipher, *pfkey;
    int             iret, times = 0, flen = 0, icount = -1, itail;
    long            lFileSize;
    unsigned char   *szPlainBlock, *szCipherBlock;
    char            *szkey;
    RSA             *pRsa;

    if((pfPlain = fopen(pszObject_file, "wb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", pszObject_file);
        return FAIL;
    }
    if((pfCipher = fopen(pszSource_file, "rb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", pszSource_file);
        return FAIL;
    }

    pRsa = RSA_new();
    
    pRsa = RSA_read_privatekey(RSA_PRIVATE_KEY_NAME);

    iret = RSA_check_key(pRsa);
    if(iret != 1)
    {
        printf("key error!\n");
        return FAIL;
    }
   
    fseek(pfCipher, 0, SEEK_END);      
    lFileSize = ftell(pfCipher);       
    rewind(pfCipher);                  

    flen = RSA_size(pRsa);
    itail = flen - 11;
   
    szPlainBlock = (char *)malloc(flen);
    szCipherBlock = (char *)malloc(flen);

    printf("RSA_Decrypt begin ......\n");
    while(!feof(pfCipher)) {
        iret = fread(szCipherBlock, sizeof(char), flen, pfCipher);
		//printf("read len: %d\n", iret);
		if (!iret)
			break;
        iret = RSA_private_decrypt(flen, szCipherBlock, szPlainBlock, pRsa, RSA_PKCS1_PADDING);
        if(iret < 0) {
            printf("RSA_private_decrypt err!\n");
            return FAIL;
        }
		//printf("decrypt len: %d\n", iret);
		fwrite(szPlainBlock, sizeof(char), iret, pfPlain);
    }

    printf("RSA_Decrypt OK!\n");

    fclose(pfPlain);
    fclose(pfCipher);
    free(szPlainBlock);
    free(szCipherBlock);
    RSA_free(pRsa);
    return SUCCESS;
}

RSA *RSA_read_privatekey(char *pszSource_file)
{
    FILE *pfkey;
    RSA  *pRsa;

    if((pfkey = fopen(pszSource_file, "rb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", pszSource_file);
        exit(0);
    }

    pRsa = RSA_new();
    pRsa = PEM_read_RSAPrivateKey(pfkey, NULL, NULL, NULL);

    return pRsa;
}

RSA *RSA_read_publickey(char *pszSource_file)
{
    FILE *pfkey;
    RSA  *pRsa;

    if((pfkey = fopen(pszSource_file, "rb")) == NULL)
    {
        printf ("==============\nopen file [ %s ] error!\n==============\n", pszSource_file);
        exit(0);
    }

    pRsa = RSA_new();
    pRsa = PEM_read_RSAPublicKey(pfkey, NULL, NULL, NULL);

    return pRsa;
}